const Vocabulary = require('../../database/models/vocabulary');
const VocabularyOperations = require('./vocabularyOperations');

class VocabularyService {
  constructor(db) {
    this.vocabularyModel = new Vocabulary(db);
  }

  /**
   * Initialize the vocabulary service
   */
  async init() {
    await this.vocabularyModel.initTable();
  }

  /**
   * Add a new word
   * @param {Object} wordData - Word data to add
   * @returns {Promise} - Promise that resolves with the added word ID
   */
  async addWord(wordData) {
    try {
      return await this.vocabularyModel.addWord(wordData);
    } catch (err) {
      throw new Error(`Failed to add word: ${err.message}`);
    }
  }

  /**
   * Get a word by ID
   * @param {number} id - Word ID
   * @returns {Promise} - Promise that resolves with the word data
   */
  async getWordById(id) {
    try {
      return await this.vocabularyModel.getWordById(id);
    } catch (err) {
      throw new Error(`Failed to get word by ID: ${err.message}`);
    }
  }

  /**
   * Get a word by text with full details
   * @param {string} word - Word text
   * @returns {Promise} - Promise that resolves with the word data including definitions and examples
   */
  async getWordByText(word) {
    try {
      console.log('VocabularyService: Getting word by text:', word);
      const result = await this.vocabularyModel.getWordByText(word);
      console.log('VocabularyService: Got result from model:', result);
      return result;
    } catch (err) {
      console.error('VocabularyService: Error getting word by text:', err);
      throw new Error(`Failed to get word by text: ${err.message}`);
    }
  }

  /**
   * Search for words
   * @param {string} pattern - Search pattern
   * @returns {Promise} - Promise that resolves with the matching words
   */
  async searchWords(pattern) {
    try {
      return await this.vocabularyModel.searchWords(pattern);
    } catch (err) {
      throw new Error(`Failed to search words: ${err.message}`);
    }
  }

  /**
   * Search for words with prefix matching
   * @param {string} prefix - Prefix to search for
   * @param {number} limit - Maximum number of results to return
   * @returns {Promise} - Promise that resolves with the matching words
   */
  async searchWordsByPrefix(prefix, limit = 10) {
    try {
      return await this.vocabularyModel.searchWordsByPrefix(prefix, limit);
    } catch (err) {
      throw new Error(`Failed to search words by prefix: ${err.message}`);
    }
  }

  /**
   * Search for words with suffix matching
   * @param {string} suffix - Suffix to search for
   * @param {number} limit - Maximum number of results to return
   * @returns {Promise} - Promise that resolves with the matching words
   */
  async searchWordsBySuffix(suffix, limit = 10) {
    try {
      return await this.vocabularyModel.searchWordsBySuffix(suffix, limit);
    } catch (err) {
      throw new Error(`Failed to search words by suffix: ${err.message}`);
    }
  }

  /**
   * Search for similar words using fuzzy matching
   * @param {string} word - Word to find similar words for
   * @param {number} limit - Maximum number of results to return
   * @returns {Promise} - Promise that resolves with the similar words
   */
  async searchSimilarWords(word, limit = 10) {
    try {
      return await this.vocabularyModel.searchSimilarWords(word, limit);
    } catch (err) {
      throw new Error(`Failed to search similar words: ${err.message}`);
    }
  }

  /**
   * Get words with pagination
   * @param {number} limit - Number of words to return
   * @param {number} offset - Number of words to skip
   * @returns {Promise} - Promise that resolves with the words
   */
  async getWords(limit = 10, offset = 0) {
    try {
      const result = await this.vocabularyModel.getWords(limit, offset);
      return result;
    } catch (err) {
      throw new Error(`Failed to get words: ${err.message}`);
    }
  }

  /**
   * Update word's known status
   * @param {string} word - Word text
   * @param {string} status - Status ('YES' or 'NO')
   * @returns {Promise} - Promise that resolves with the update result
   */
  async updateKnownStatus(word, status) {
    return VocabularyOperations.updateKnownStatus(this.vocabularyModel, word, status);
  }

  /**
   * Update word's IELTS tag
   * @param {string} word - Word text
   * @param {string} tag - Tag ('YES' or 'NO')
   * @returns {Promise} - Promise that resolves with the update result
   */
  async updateIeltsTag(word, tag) {
    return VocabularyOperations.updateIeltsTag(this.vocabularyModel, word, tag);
  }

  /**
   * Add a query history record
   * @param {string} word - The queried word
   * @returns {Promise} - Promise that resolves with the operation result
   */
  async addQueryHistory(word) {
    try {
      return await this.vocabularyModel.addQueryHistory(word);
    } catch (err) {
      throw new Error(`Failed to add query history: ${err.message}`);
    }
  }

  /**
   * Get query history
   * @param {number} limit - Number of records to return
   * @returns {Promise} - Promise that resolves with the query history
   */
  async getQueryHistory(limit = 50) {
    try {
      return await this.vocabularyModel.getQueryHistory(limit);
    } catch (err) {
      throw new Error(`Failed to get query history: ${err.message}`);
    }
  }

  /**
   * Clear query history
   * @returns {Promise} - Promise that resolves with the operation result
   */
  async clearQueryHistory() {
    try {
      return await this.vocabularyModel.clearQueryHistory();
    } catch (err) {
      throw new Error(`Failed to clear query history: ${err.message}`);
    }
  }

  /**
   * Remove a single item from query history
   * @param {string} word - The word to remove from history
   * @returns {Promise} - Promise that resolves with the operation result
   */
  async removeQueryHistoryItem(word) {
    try {
      return await this.vocabularyModel.removeQueryHistoryItem(word);
    } catch (err) {
      throw new Error(`Failed to remove query history item: ${err.message}`);
    }
  }
}

module.exports = VocabularyService;
